#include "IntegrationTestFramework.h"

#include <boost/range/combine.hpp>

#include <EngineInterface/SimulationFacade.h>
#include <EngineInterface/SimulationParameters.h>

#include <EngineTestData/DescriptionTestDataFactory.h>

#include <EngineImpl/SimulationFacadeImpl.h>

IntegrationTestFramework::TestSuiteContext IntegrationTestFramework::_globalContext;

void IntegrationTestFramework::TestSuiteContext::cleanup()
{
    if (simulationFacade) {
        simulationFacade->closeSimulation();
        simulationFacade.reset();
    }
}

void IntegrationTestFramework::cleanupGlobalContext()
{
    _globalContext.cleanup();
}

IntegrationTestFramework::IntegrationTestFramework(IntVector2D const& worldSize)
    : _worldSize(worldSize)
{
    if (_globalContext.simulationFacade == nullptr) {
        _globalContext.simulationFacade = std::make_shared<_SimulationFacadeImpl>();
    }

    _simulationFacade = _globalContext.simulationFacade;
    if (_simulationFacade->getWorldSize() != worldSize) {
        _simulationFacade->closeSimulation();
        for (int i = 0; i < MAX_COLORS; ++i) {
            _parameters.radiationType1_strength.baseValue[i] = 0;
        }
        _simulationFacade->newSimulation(0, _worldSize, _parameters);
    } else {
        _simulationFacade->clear();
        _simulationFacade->setPreviewData(Description());
        _simulationFacade->setCurrentTimestepForPreview(0);
        _simulationFacade->setCurrentTimestep(0);
        for (int i = 0; i < MAX_COLORS; ++i) {
            _parameters.radiationType1_strength.baseValue[i] = 0;
        }
        _simulationFacade->setSimulationParameters(_parameters);
    }

}

IntegrationTestFramework::~IntegrationTestFramework()
{
}

double IntegrationTestFramework::getEnergy(Description const& data) const
{
    double result = 0;
    for (auto const& cell : data._cells) {
        result += cell._usableEnergy + cell._rawEnergy;
    }
    for (auto const& creature : data._creatures) {
        for (auto const& cell : creature._cells) {
            result += cell._usableEnergy + cell._rawEnergy;
        }
    }
    for (auto const& particle : data._particles) {
        result += particle._energy;
    }
    return result;
}

bool IntegrationTestFramework::compare(Description left, Description right) const
{
    return DescriptionTestDataFactory::get().compare(left, right);
}

bool IntegrationTestFramework::compare(CellDescription left, CellDescription right) const
{
    return DescriptionTestDataFactory::get().compare(left, right);
}

bool IntegrationTestFramework::compare(ParticleDescription left, ParticleDescription right) const
{
    return DescriptionTestDataFactory::get().compare(left, right);
}
